#include "db.h"
#include "utilities.h"

#define freeNode(node) {\
	free((node)->name); \
	free(node); \
}

#define mod0 (char)1
#define mod1 (char)2
#define mod2 (char)4
#define mod3 (char)8
#define mod4 (char)16
#define mod_non (char)(2*2*2*2*2*2*2)

/* struct that represent one command */
struct command cmd[] = {
		{"mov","0000", mod0+mod1+mod2+mod3+mod4 ,mod1+mod2+mod3+mod4},
		{"cmp","0001", mod0+mod1+mod2+mod3+mod4 , mod0+mod1+mod2+mod3+mod4},
		{"add","0010", mod0+mod1+mod2+mod3+mod4 , mod1+mod2+mod3+mod4},
		{"sub","0011", mod0+mod1+mod2+mod3+mod4 , mod1+mod2+mod3+mod4},
		{"not","0100", mod_non , mod1+mod2+mod3+mod4},
		{"clr","0101", mod_non , mod1+mod2+mod3+mod4},
		{"lea","0110", mod1+mod2+mod3 ,mod1+mod2+mod3+mod4},
		{"inc","0111", mod_non , mod1+mod2+mod3+mod4},
		{"dec","1000", mod_non , mod1+mod2+mod3+mod4},
		{"jmp","1001", mod_non , mod1},
		{"bne","1010", mod_non , mod1},
		{"red","1011", mod_non , mod1+mod2+mod3+mod4},
		{"prn","1100", mod_non , mod0+mod1+mod2+mod3+mod4},
		{"jsr","1101", mod_non , mod1},
		{"rts","1110", mod_non , mod_non},
		{"hlt","1111", mod_non , mod_non}
};

node_ptr ext_list;
node_ptr ent_list;
node_ptr lable_list;
node_ptr lable_list_tmp;
node_ptr data_str_list;

void clear_list()
{
	ext_list = NULL;
	ent_list = NULL;
	lable_list = NULL;
	lable_list_tmp = NULL;
	data_str_list = NULL;
}

node_ptr list_find(node_ptr list_head_ptr, char *str)
{
	node_ptr item = list_head_ptr;

	while(item != NULL)
	{
		if (!strcmp(item->name, str))
			break;
		item = item->next;
	}	

	return item;
}

node_ptr list_add(node_ptr list_head_ptr, char *name, int value)
{
	node_ptr new_item = (node_ptr) malloc(sizeof(struct define_info));

	/*DBG_OUT("Added: "); DBG_OUT(name); DBG_OUT("==="); DBG_OUT(value); DBG_OUT("\n");*/
	/*DBG_OUT("Added: "); DBG_OUT(name); DBG_OUT("\n");*/

	new_item->name = (char *)calloc(strlen(name)+1,sizeof(char));
	strcpy(new_item->name, name);
	new_item->value = value;
	new_item->next = NULL;
    if (list_head_ptr != NULL)
    {
    	node_ptr p = list_head_ptr;
    	while(p->next != NULL)
    		p = p->next;
    	p->next = new_item;
    }
	else
	{
		list_head_ptr = new_item;
	}

	return list_head_ptr;
}

/* free the list */
void listFree(node_ptr list_head_ptr)
{
	node_ptr tmp;
	while(list_head_ptr != NULL)
	{
		tmp = list_head_ptr->next;
		freeNode(list_head_ptr)
		list_head_ptr = tmp;
	}
}

/* remove node from the list */
node_ptr removeNode(node_ptr list_head, node_ptr needToRemove)
{
	node_ptr p = list_head;
	node_ptr p2;
	if(list_head == needToRemove)
	{
		p = p->next;
		freeNode(list_head)
		return p;
	}
	
	while(p->next != needToRemove)
	{
		p2 = p->next;
	}
	p2 = p->next;
	p2 = p2->next;
	freeNode(list_head)
	p->next = p2;
	return list_head;
}

/* find the command index
 * return the index of the command, if not exict return numOfCommands */
int findTheCommand(char *theCommand)
{
	int i = 0;
	while(numOfCommands>i)
	{
		if(strcmp((cmd[i]).name,theCommand) == 0)
		{
			break;
		}
		i++;
	}
	return i;
}

/* check if the operand type is legal
 * mode: the operand types thats are legal
 * check: the operand type that the function check if leagal
 * return true if check is legal and false otherwish */
int checkIfLegalOpType(char mode, int check)
{
	char mask = 1;
	
	if(check > 7 || check <0)
	{
		return false;
	}
	
	mask = mask << (check);
	if((mode & mask) != 0)
	{
		return true;
	}
	return false;
}